﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Roslyn.Compilers;
using Roslyn.Compilers.Compilation;
using Roslyn.Compilers.Common;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;
using Roslyn.Services.CSharp;
using Analysis.Rules;
using Analysis.DependencyGenerators;

namespace Analysis
{
    public class ClassDependencies
    {
        private readonly IRoslynHelper helper = new RoslynHelper();

        public IEnumerable<Dependency> GetDependencies(BlockSyntax bs, IDocument document)
        {
            return
                GetDependencies<ObjectCreationExpressionSyntax>(AnalysisKind.NewSimpleTypes, new ObjectInvocationIsSimpleTypeVolatileChecker(helper), bs, document)
            .Concat(
                GetDependencies<ObjectCreationExpressionSyntax>(AnalysisKind.NewExpr, new ConcreteClassFromSolutionVolatileChecker(helper), bs, document)
            .Concat(
                GetDependencies<InvocationExpressionSyntax>(AnalysisKind.FactoryMethod, new ObjectInvocationIsDisposableVolatileChecker(helper), bs, document)
            .Concat(
                GetDependencies<InvocationExpressionSyntax>(AnalysisKind.StaticMethod, new StaticMethodVolatileChecker(helper), bs, document)
            .Concat(
                new CyclematicComplexityGenerator().GetBlockDependencies(AnalysisKind.CyclomaticComplexity, bs, document)))));
        }

        private IEnumerable<Dependency> GetDependencies<TExpressionSyntax>(AnalysisKind kind, IVolatileChecker volatilechecker , BlockSyntax bs, IDocument document) 
            where TExpressionSyntax : ExpressionSyntax
        {
            return bs.DescendantNodes().OfType<TExpressionSyntax>()
                .Where(oce => volatilechecker.IsVolatile(oce, document))
                .Select(oce => new Dependency { Kind = kind, In = oce });
        }
    }
}
